package com.cmcc.cmii.common.exceptions;

import com.cmcc.cmii.common.enums.ResultEnum;
import com.cmcc.cmii.common.result.ResultVo;
import com.cmcc.cmii.common.result.ResultVoUtils;
import com.cmcc.cmii.common.result.TableVo;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.WebExchangeBindException;


import java.io.IOException;
import java.util.ArrayList;

/**
 * @author Thanks
 */
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
    //参数校验失败
    @ExceptionHandler(WebExchangeBindException.class)
    public ResultVo webExchangeBindExceptionHandler(WebExchangeBindException ex){
        return resultFormat(ResultEnum.NULL_PARAM_ERROR.getCode(),ex,ex.getBindingResult().getFieldError().getDefaultMessage());
    }
    //参数校验失败
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultVo argumentNotValidHandler(MethodArgumentNotValidException ex){

        return resultFormat(ResultEnum.NULL_PARAM_ERROR.getCode(),ex,ex.getBindingResult().getFieldError().getDefaultMessage());
    }

    //运行时异常
    @ExceptionHandler(RuntimeException.class)
    public ResultVo runtimeExceptionHandler(RuntimeException ex){
        String message = ex.getMessage();
        System.out.println("============================="+message);
        return resultFormat(ResultEnum.RUNTIME_ERROR.getCode(),ex,ResultEnum.RUNTIME_ERROR.getMessage());
    }

    //空指针异常
    @ExceptionHandler(NullPointerException.class)
    public ResultVo nullPointerExceptionHandler(NullPointerException ex) {
        return resultFormat(ResultEnum.NULL_PARAM_ERROR.getCode(),ex,ResultEnum.NULL_PARAM_ERROR.getMessage());
    }

    //类型转换异常
    @ExceptionHandler(ClassCastException.class)
    public ResultVo classCastExceptionHandler(ClassCastException ex) {
        return resultFormat(ResultEnum.CLASS_CAST_ERROR.getCode(),ex,ResultEnum.CLASS_CAST_ERROR.getMessage());
    }


    //IO异常
    @ExceptionHandler(IOException.class)
    public ResultVo iOExceptionHandler(IOException ex) {
        return resultFormat(ResultEnum.IO_ERROR.getCode(), ex,ResultEnum.IO_ERROR.getMessage());
    }

    //未知方法异常
    @ExceptionHandler(NoSuchMethodException.class)
    public ResultVo noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        return resultFormat(ResultEnum.NO_SUCH_METHOD.getCode(), ex,ResultEnum.NO_SUCH_METHOD.getMessage());
    }

    //数组越界异常
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public ResultVo indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        return resultFormat(ResultEnum.INDEX_OUT_OF_BOUNDS.getCode(), ex,ResultEnum.INDEX_OUT_OF_BOUNDS.getMessage());
    }

    //400错误
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public ResultVo requestNotReadable(HttpMessageNotReadableException ex) {
        return resultFormat(HttpStatus.BAD_REQUEST.value(), ex,"requestNotReadable");
    }

    //400错误
    @ExceptionHandler({TypeMismatchException.class})
    public ResultVo requestTypeMismatch(TypeMismatchException ex) {
        return resultFormat(HttpStatus.BAD_REQUEST.value(), ex,"TypeMismatchException");
    }

    //400错误
    /*@ExceptionHandler({MissingServletRequestParameterException.class})
    public ResultVo requestMissingServletRequest(MissingServletRequestParameterException ex) {
        return resultFormat(HttpStatus.BAD_REQUEST.value(), ex,"MissingServletRequest");
    }*/

    /*//405错误
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public ResultVo request405(HttpRequestMethodNotSupportedException ex) {
        return resultFormat(HttpStatus.METHOD_NOT_ALLOWED.value(), ex,"Method Not Allowed");
    }

    //406错误
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public ResultVo request406(HttpMediaTypeNotAcceptableException ex) {

        return resultFormat(HttpStatus.NOT_ACCEPTABLE.value(), ex,"Not Acceptable");
    }*/

    //500错误
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public ResultVo server500(RuntimeException ex) {
        return resultFormat(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex,HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
    }

    //栈溢出
    @ExceptionHandler({StackOverflowError.class})
    public ResultVo requestStackOverflow(StackOverflowError ex) {
        return resultFormat(ResultEnum.STACK_OVER_FLOW.getCode(), ex,ResultEnum.STACK_OVER_FLOW.getMessage());
    }

    //除数不能为0
    @ExceptionHandler({ArithmeticException.class})
    public ResultVo arithmeticException(ArithmeticException ex) {
        return resultFormat(ResultEnum.ARITHMETIC_ERROR.getCode(), ex,ResultEnum.ARITHMETIC_ERROR.getMessage());
    }

    /**
     * 用户未登录 或未授权
     * @param ex
     * @return
     */
    @ExceptionHandler(SecurityException.class)
    public TableVo securityException(SecurityException ex){
        return TableVo.builder()
                .code(1)
                .count(0L)
                .msg(ex.getMessage())
                .data(new ArrayList<>())
                .build();
    }

    //其他错误
    @ExceptionHandler({Exception.class})
    public ResultVo exception(Exception ex) {
        return resultFormat(ResultEnum.UNKNOWN_ERROR.getCode(), ex,ResultEnum.UNKNOWN_ERROR.getMessage());
    }








    private <T extends Throwable> ResultVo resultFormat(Integer code, T ex,String returnMsg) {
        ex.printStackTrace();
        return ResultVoUtils.error(code,returnMsg);
    }


}
